from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.remote.webelement import WebElement

from common.decorators import log4gs
from common.functions import get_xpath, has_text_wait


@log4gs
class DropDownSelect(object):
    """在下拉选择器里面选择一个选项"""

    #selectClassName = "ivu-select"
    selectItemClassName = "ivu-select-item"

    def __init__(self, select_elem, text):
        """
        :param select_elem: 选择器dom，要求在xpath时，复制的节点是class_name里包含ivu-select
        :param text: 要选项的文本

        使用方法：
            DropDownSelect(select_elem, "男")   # 在性别下拉列表里面选择“男”
        """

        # ElementBaseLabel返回的不是WebElement实例，兼容之。
        # target_element协议
        if not isinstance(select_elem, WebElement):
            select_elem = select_elem.target_element

        select_elem.click()
        self.items = select_elem.find_elements_by_class_name(self.selectItemClassName)
        if not self.items:
            try:
                raise NoSuchElementException("下拉列表为空，没有供选择的项")
            except NoSuchElementException:
                self.log.error("下拉列表为空，没有供选择的项", exc_info=True)
        if self.items:
            for item in self.items:
                has_text_wait(item)
                if item.text.strip() == text:
                    item.click()
                    return
            raise NoSuchElementException("选择器里面没有'{}'选项".format(text))
        else:
            raise NoSuchElementException("选择器里面没有选项")


@log4gs
class OperateSelect(object):
    """在列表里面，往往有个操作列，这里提供：根据操作里面的按钮名称或者按钮序号来获取按钮，并直接点击"""

    ### 查看前端源码发现操作的提示内容用了两种类
    tipClassName1 = "ivu-tooltip"
    tipClassName2 = "ivu-poptip"   # ""ivu-poptip-body-content"

    def __init__(self, elem, tip=None, btn_index=None, column_index=-1):
        """
        :param elem: 需要操作的行元素
        :param tip: 按钮上面的提示内容
        :param btn_index: 按钮的序号
        :param column_index: 操作列的序号，默认操作列在表的最后一列

        使用方法：
            OperateSelect(row_ele, tip="编辑")    # 点击row_ele行元素中，操作列的编辑按钮
            OperateSelect(row_ele, btn_index=0)    # 点击row_ele行元素中，操作列的第一个按钮
        """
        if not tip and not isinstance(btn_index, int):
            try:
                raise ValueError("按钮提示或者按钮序号至少提供一个")
            except ValueError:
                self.log.error("按钮提示或者按钮序号至少提供一个", exc_info=True)

        self.operate_td = elem.find_elements_by_tag_name('td')[column_index]
        try:
            self.operate_btns = self.operate_td.find_elements_by_class_name(self.tipClassName1)
            if not self.operate_btns:
                self.operate_btns = self.operate_td.find_elements_by_class_name(self.tipClassName2)
        except Exception:
            self.log.error("通过类名'{}'、'{}'都没有找到操作按钮".format(self.tipClassName1, self.tipClassName2))
        finally:
            if tip:
                for btn in self.operate_btns:
                    ### 由于按钮的tip都是dispaly:none的，用selenium的text取不到，因此用js获取
                    js = "return arguments[0].textContent"
                    text = elem.driver.execute_script(js, btn)
                    self.log.debug(text)
                    if text.strip() == tip:
                        btn.click()
                        return
                try:
                    raise NoSuchElementException("没有找到tip是'{}'的操作按钮".format(tip))
                except NoSuchElementException:
                    self.log.error("没有找到tip是'{}'的操作按钮".format(tip), exc_info=True)
            else:
                try:
                    self.operate_btns[btn_index].click()
                except Exception:
                    self.log.error("通过序号‘{}’没有找到操作按钮".format(btn_index))